-
- #define F_CPU 8000000UL
-
- #include <avr/io.h>
- #include <stdio.h>
- #include <inttypes.h>
- #include <stdint.h>
- #include <avr/pgmspace.h>
- #include <avr/interrupt.h>
- #include <util/delay.h>
- #include <util/atomic.h>
- #include <avr/wdt.h>
-
- #define BAUDRATE 9600
-
- #define NTCBETA 3380
- #define NTCRES 10000
- #define NTCFIXEDRES 10000
-
- #define ONTEMP 4.0 // °C
- #define OFFTEMP 2.0 // °C
-
- #define POWERONDELAY 5 // sec
- #define ONTIME 60 // sec
- #define OFFTIME 180 // sec
-
-
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
- // attiny48 //
- // pins //
- // 1 : PB5 reset, ADC0 //
- // 2 : PB3 ADC3 / RELAY //
- // 3 : PB4 ADC2 / CAP //
- // 4 : gnd //
- // 5 : PB0 Mosi, AREF //
- // 6 : PB1 Miso / TX //
- // 7 : PB2 SCK, ADC1 / NTC //
- // 8 : VCC //
- // //
- // VCC -> 10k -> NTC -> GND //
- // NTC: NTSD1XH103FPB40 https://media.digikey.com/pdf/Data%20Sheets/Murata%20PDFs/NTSD1%20Spec.pdf //
- // Beta: 3380 //
- //////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
- #define RELAYPIN PINB
- #define RELAYDDR DDRB
- #define RELAYPORT PORTB
- #define RELAYBIT 3
-
- #define CAPPIN PINB
- #define CAPDDR DDRB
- #define CAPPORT PORTB
- #define CAPBIT 4
-
- #define NTCPIN PINB
- #define NTCPORT PORTB
- #define NTCDDR DDRB
- #define NTCMUX 1
- #define NTCBIT 2
-
- #define UARTTXPIN PINB
- #define UARTTXPORT PORTB
- #define UARTTXDDR DDRB
- #define UARTTXBIT 1
-
- //////////////////////////////////
- // Do not edit bellow this line //
- //////////////////////////////////
-
-
- volatile uint32_t timeSecs = 68300;
- volatile uint32_t timeCycles = 0;
- volatile uint8_t status = 0;
- volatile uint16_t timeStatus = 0;
- volatile float temperature = 0.0;
-
-
-
- void usart_bitdelay() {
- _delay_us(1000000/BAUDRATE); // 1e6 us / baudrate
- }
-
- void usart_putchar(char data) {
- // 0 start, LSB...MSB, 2 stop
- uint8_t i;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- // start bit, 0
- UARTTXPORT &= ~(1 << UARTTXBIT);
- usart_bitdelay();
-
- // 8 data bits
- for (i = 8; i != 0; i--) {
- if (data & 0x01) {
- // 1
- UARTTXPORT |= (1 << UARTTXBIT);
- } else {
- // 0
- UARTTXPORT &= ~(1 << UARTTXBIT);
- }
- data >>= 1;
- usart_bitdelay();
- }
-
-
- // stop bit, 1
- UARTTXPORT |= (1 << UARTTXBIT);
- usart_bitdelay();
- usart_bitdelay();
- }
- }
-
- static FILE mystdout = FDEV_SETUP_STREAM(usart_putchar, NULL, _FDEV_SETUP_WRITE);
-
- void printData() {
- uint32_t lsecs;
- uint16_t lhours;
- uint8_t lmins;
-
- uint8_t lstatus;
- uint16_t ltstatus;
-
- float ltemp;
-
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- lsecs = timeSecs;
- lstatus = status;
- ltstatus = timeStatus;
- ltemp = temperature;
- };
-
- lhours = lsecs / (uint32_t)3600;
- lsecs = lsecs - (lhours * (uint32_t)3600);
-
- lmins = lsecs / (uint32_t)60;
- lsecs = lsecs - (lmins * (uint32_t)60);
-
- printf_P(PSTR("% 5u:%02u:%02u "), lhours, lmins, lsecs);
-
- printf_P(PSTR("Temperature: % 6.2f°C Status: %d: "), ltemp, lstatus);
- if (lstatus == 0) {
- printf_P(PSTR("RCLockout "));
- } else if (lstatus == 1) {
- printf_P(PSTR("PowerOnDelay"));
- } else if (lstatus == 2) {
- printf_P(PSTR("Off "));
- } else if (lstatus == 3) {
- printf_P(PSTR("OffDelay "));
- } else if (lstatus == 4) {
- printf_P(PSTR("On "));
- } else if (lstatus == 5) {
- printf_P(PSTR("OnDelay "));
- }
- printf_P(PSTR(" Since: %5u secs Reset: "), ltstatus);
- if (MCUSR & (1<<WDRF)) { printf_P(PSTR("Watchdog")); }
- if (MCUSR & (1<<BORF)) { printf_P(PSTR("Brownout")); }
- if (MCUSR & (1<<EXTRF)) { printf_P(PSTR("External")); }
- if ( ! ((MCUSR & (1<<WDRF)) | (MCUSR & (1<<BORF)) | (MCUSR & (1<<EXTRF)) | (MCUSR & (1<<PORF)))) {
- printf_P(PSTR("None"));
- }
- printf_P(PSTR("\r\n"));
- }
-
-
- void relay(uint8_t state) {
- if (state == 0) {
- RELAYPORT &= ~(1<<RELAYBIT);
- } else if (state == 1) {
- RELAYPORT |= (1<<RELAYBIT);
- }
- }
-
-
- void calculateTemperature() {
- uint16_t adc = 0;
- uint8_t loop;
- float resistance;
-
- // sample and discard first sample
- ADCSRA |= (1<<ADSC);
- while (ADCSRA & (1<<ADSC));
-
- // oversample, 16
- for (loop = 0; loop < 16; loop++) {
- ADCSRA |= (1<<ADSC);
- while (ADCSRA & (1<<ADSC));
- adc += ADC;
- }
-
- // vvv due to oversampling
- resistance = ((float)adc * (float)NTCFIXEDRES) / ((1024*16)-adc);
-
-
- // 1/T0 1 / B R R25 K->C
- temperature = 1.0 / ( (1.0/298.15) + (1.0/(float)NTCBETA) * log(resistance / (float)NTCRES) ) - 273.15;
- }
-
- int main(void) {
- uint32_t ltime = 0;
-
- // set up watchdog timer
- wdt_enable(WDTO_8S);
-
-
- // set relay pin to output, set to off
- RELAYDDR |= (1<<RELAYBIT);
- relay(0);
-
- // set capacitor pin to input with pullup
- CAPDDR &= ~(1<<CAPBIT);
- CAPPORT |= (1<<CAPBIT);
-
- // set adc
- // attiny85 datasheet recommand 50-200kHz for maximum resolution
- // reference of 000 set to VCC, default to 000
- // ADMUX |= (1<<REFS0); // external ref
- ADMUX |= NTCMUX;
- // prescaller /128 = 62.5k@8MHz = 111
- ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
-
- // set timer0
- TCCR0B |= (1<<CS02) | (1<<CS00); // /1024 prescalling
- TIMSK |= (1<<TOIE0); // overflow interrupt enable
-
- // set uart
- UARTTXDDR |= (1<<UARTTXBIT);
- UARTTXPORT |= (1<<UARTTXBIT);
- stdout = &mystdout;
-
-
- printf_P(PSTR("\r\n"));
- printf_P(PSTR("Reset! \r\n"));
-
- // turn on interrupts
- sei();
-
- // look if the power reset flag is set, if so reset the reset sources
- if (MCUSR & (1<<PORF)) {
- MCUSR &= ~((1<<WDRF) | (1<<BORF) | (1<<EXTRF) | (1<<PORF));
- }
-
-
- // Main loop
- while(1) {
- // wait for a second to pass
- while (ltime == timeSecs);
- ltime = timeSecs;
-
- calculateTemperature();
-
- if (status == 0) {
- // lock out
- // check for cap
- if (CAPPIN & (1<<CAPBIT)) {
- // cap is discharged, release lockout
- status = 1;
- }
- } else if (status == 1) {
- // minimum poweron delay
- if (timeStatus >= POWERONDELAY) {
- status = 2;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- timeStatus = 0;
- }
- }
- } else if (status == 2) {
- // Off
- relay(0);
- if (temperature >= ONTEMP) {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- timeStatus = 0;
- }
- status = 5;
- }
- } else if (status == 3) {
- // Off with delay
- relay(0);
- if (timeStatus >= OFFTIME) {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- timeStatus = 0;
- }
- status = 2;
- }
-
- } else if (status == 4) {
- // On
- relay(1);
- if (temperature <= OFFTEMP) {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- timeStatus = 0;
- }
- status = 3;
- }
- } else if (status == 5) {
- // On with delay
- relay(1);
- if (timeStatus >= ONTIME) {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- timeStatus = 0;
- }
- status = 4;
- }
- }
-
- printData();
- wdt_reset();
- };
-
- return(0);
- }
-
-
- ISR(TIM0_OVF_vect) {
- // time keeping
- timeCycles += 262144; // 8 bits timer with /1024 prescaller
- if (timeCycles >= F_CPU) {
- timeCycles -= F_CPU;
- timeSecs++;
- timeStatus++;
- }
-
- }
-